﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows;
using System.Diagnostics;
using System.Threading;
using Hi_Baidu.FileShare;
using Hi_Baidu.FileShare.User;
using System.Windows.Controls;
using System.Windows.Forms;
using Hi_Baidu.UI.Compoment;
using Hi_Baidu.Enum.DigHole;
using Hi_Baidu.Packet;
using Hi_Baidu.Cache.CacheObject;
using Hi_Baidu.Cache;
using System.Net;
using Hi_Baidu.FileShare.ListType;
using Hi_Baidu.FileShare.Model;
using Hi_Baidu.FileShare.Packet.InPacket;

namespace Hi_Baidu.Plugin
{
    public class FileShare : TalkWindowNetworkWindowPlugin
    {
        bool IS_FOUND = false;
        String ProcessName = "FileShare";
        String TabName = "文件共享";
        System.Timers.Timer CheckTimer;
        private delegate void ADDITEM();
        TabItem tabItem;
        private NotifySendFileManager notifySendFileManager = new NotifySendFileManager();

        public FileShare()
        {
            this.name = "文件共享台插件";
            this.description = "提供了基础的文件共享相关操作";
            this.author = "剑走偏锋";
            this.version = "1.0.0.0";
            this.toolTip = "文件共享";
            this.pluginImageSize = new System.Windows.Size(32, 32);
            this.pluginImagePath = Directory.GetCurrentDirectory() + "../../Plugins/com.Hi_Baidu.FileShare/Image/dellipack_icons_002.png";
            Globle.fileShare = this;
        }

        public override void AppendEvent()
        {
            if (this.Control != null)
            {
                this.Control.MouseDown += new System.Windows.Input.MouseButtonEventHandler(Control_MouseDown);
            }
        }

        void Control_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            //开始发送P文件端口打洞
            if (!this.RefFriend.HasFilePortHole)
            {
                RefFriend.DigHole(ForUser.DIC_USERINFO["USERNAME"], BitConverter.GetBytes(ForUser.TRANSFER_FILE_PORT), (int)DigType.FILE_TRANSFER, ForUser.SESSION_CODE, ServerIP, ServerPort);
            }
            if (!GetTabItemExists(TabName))
            {
                using (OpenFileDialog openFileDialog = new OpenFileDialog())
                {
                    openFileDialog.Title = "请选择要发送的文件";
                    //用户选择了文件
                    if (openFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        String FilePath = openFileDialog.FileName;
                        String FileName = openFileDialog.SafeFileName;
                        String[] FileData = FileName.Split('.');
                        if (!this.notifySendFileManager.Equals(FilePath))
                        {
                            System.Windows.Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new ADDITEM(CreateTabItem));
                            //开始组建控件
                            SendFileControl sendFileControl = new SendFileControl();
                            sendFileControl.FilePath = FilePath;
                            sendFileControl.UseType = SendFileControl.ControlType.Send;
                            sendFileControl.CancleSendFile += new EventHandler<SendFileControl.CancleSendFileEventArgs>(sendFileControl_CancleSendFile);
                            sendFileControl.Height = 85;
                            sendFileControl.FileName = FileName;
                            sendFileControl.FileExt = FileData[FileData.Length - 1];
                            sendFileControl.SetFileSize();
                            sendFileControl.FileIcon = Hi_Baidu.Model.ProcessModel.IOProcessModel.ConvertToWPF(Hi_Baidu.Model.ProcessModel.IOProcessModel.GetIconByFileType("." + FileData[FileData.Length - 1], true));
                            ((this.tabItem.Content as Grid).Children[0] as WrapPanel).Children.Add(sendFileControl);
                            this.notifySendFileManager.Add(sendFileControl);
                            NoticeSendFileToFriend(sendFileControl);
                        }
                    }
                }
            }
            else 
            {
                using (OpenFileDialog openFileDialog = new OpenFileDialog())
                {
                    openFileDialog.Title = "请选择要发送的文件";
                    //用户选择了文件
                    if (openFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        String FilePath = openFileDialog.FileName;
                        String FileName = openFileDialog.SafeFileName;
                        String[] FileData = FileName.Split('.');
                        //开始组建控件
                        if (!this.notifySendFileManager.Equals(FilePath))
                        {
                            //开始组建控件
                            SendFileControl sendFileControl = new SendFileControl();
                            sendFileControl.FilePath = FilePath;
                            sendFileControl.UseType = SendFileControl.ControlType.Send;
                            sendFileControl.CancleSendFile += new EventHandler<SendFileControl.CancleSendFileEventArgs>(sendFileControl_CancleSendFile);
                            sendFileControl.Height = 85;
                            sendFileControl.FileName = FileName;
                            sendFileControl.FileExt = FileData[FileData.Length - 1];
                            sendFileControl.SetFileSize();
                            sendFileControl.FileIcon = Hi_Baidu.Model.ProcessModel.IOProcessModel.ConvertToWPF(Hi_Baidu.Model.ProcessModel.IOProcessModel.GetIconByFileType("." + FileData[FileData.Length - 1], true));
                            ((this.tabItem.Content as Grid).Children[0] as WrapPanel).Children.Add(sendFileControl);
                            this.notifySendFileManager.Add(sendFileControl);
                            NoticeSendFileToFriend(sendFileControl);
                        }
                    }
                }
            }
        }

        /// <summary>
        ///     向好友发送传送文件请求
        /// </summary>
        public void NoticeSendFileToFriend(SendFileControl sendFileControl)
        {
            if(RefFriend.OnlineState && RefFriend.HasFilePortHole)
            {
                //创建缓存
                SendFileCache sendFileCache = new SendFileCache(sendFileControl.SENDF_FILE_SESSION_CODE, sendFileControl.Key, DateTime.MaxValue);
                DeclareCacheManager.sendFileManager.Add(sendFileCache);
                //开始创建请求包头部信息
                byte[] UsernameLength = BitConverter.GetBytes(ForUser.DIC_USERINFO["USERNAME"].Length);
                byte[] FileSize = BitConverter.GetBytes(sendFileControl.FileSize);
                byte[] FileName = Encoding.Default.GetBytes(sendFileControl.FileName);
                byte[] FileNameLength = BitConverter.GetBytes(FileName.Length);
                byte[] FileSession = Encoding.Default.GetBytes(sendFileControl.SENDF_FILE_SESSION_CODE);
                byte[] FileSessionLength = BitConverter.GetBytes(FileSession.Length);
                byte[] FileExt = Encoding.Default.GetBytes(sendFileControl.FileExt);
                byte[] FileExtLength = BitConverter.GetBytes(FileExt.Length);
                byte[] IPAddress = Encoding.Default.GetBytes(Dns.GetHostAddresses(Dns.GetHostName())[0].ToString());
                byte[] IPLength = BitConverter.GetBytes(IPAddress.Length);
                byte[] FilePort = BitConverter.GetBytes(ForUser.TRANSFER_FILE_PORT);
                byte[] PackageBody = new byte[ForUser.DIC_USERINFO["USERNAME"].Length + FileName.Length + FileSession.Length + FileExt.Length + IPAddress.Length + 28];
                int Offset = 0;
                //开始组合头部信息
                Array.ConstrainedCopy(UsernameLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //用户名
                Array.ConstrainedCopy(ForUser.DIC_USERINFO["USERNAME"], 0, PackageBody, Offset, ForUser.DIC_USERINFO["USERNAME"].Length);
                Offset += ForUser.DIC_USERINFO["USERNAME"].Length;
                //文件名长度
                Array.ConstrainedCopy(FileNameLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //文件名
                Array.ConstrainedCopy(FileName, 0, PackageBody, Offset, FileName.Length);
                Offset += FileName.Length;
                //会话长度
                Array.ConstrainedCopy(FileSessionLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //会话
                Array.ConstrainedCopy(FileSession, 0, PackageBody, Offset, FileSession.Length);
                Offset += FileSession.Length;                
                //文件后缀名长度
                Array.ConstrainedCopy(FileExtLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //文件后缀名
                Array.ConstrainedCopy(FileExt, 0, PackageBody, Offset, FileExt.Length);
                Offset += FileExt.Length;
                //文件大小
                Array.ConstrainedCopy(FileSize, 0, PackageBody, Offset, 4);
                Offset += 4;
                //IP地址长度
                Array.ConstrainedCopy(IPLength, 0, PackageBody, Offset, IPLength.Length);
                Offset += 4;
                //IP地址
                Array.ConstrainedCopy(IPAddress, 0, PackageBody, Offset, IPAddress.Length);
                Offset += IPAddress.Length;
                //文件端口
                Array.ConstrainedCopy(FilePort, 0, PackageBody, Offset, FilePort.Length);

                //向好友发送传送文件请求
                byte[] protocol = ProtocolFactory.ProtocolFactory.GetProtocolFromSendFile
                    (
                        "RequstSendFile", 
                        (int)Protocol.OUT_SendFile.REQUEST_SEND_FILE, 
                        (int)Protocol.NetworkProtocol.TRANSFER_FILE, 
                        PackageBody, 
                        ProtocolFactory.ProtocolFactory.ACK.Yes, 
                        ProtocolFactory.ProtocolFactory.ENCRYPT.No, 
                        sendFileControl.SENDF_FILE_SESSION_CODE
                     );
                NetControl.Send(protocol, RefFriend.FilePort, RefFriend.IpAddress);
            }
        }

        void sendFileControl_CancleSendFile(object sender, SendFileControl.CancleSendFileEventArgs e)
        {
            foreach (TabItem item in  (this.Tag as System.Windows.Controls.TabControl).Items)
            {
                if(item.Header == this.TabName)
                {
                    ((item.Content as Grid).Children[0] as WrapPanel).Children.Remove(e.Control);
                    this.notifySendFileManager.Remove(e.Control);
                    break;
                }
            }
        }
        
        /// <summary>
        ///     好友取消了文件的传送请求     
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.FileShare.Packet.InPacket.PassSendFilePacket">
        ///     <para>
        ///         取消文件请求包
        ///     </para>
        /// </param>
        public void CancleSendFile(PassSendFilePacket inpackage)
        {
            foreach (SendFileControl control in ((tabItem.Content as Grid).Children[0] as WrapPanel).Children)
            {
                if (control.SENDF_FILE_SESSION_CODE == inpackage.GetFileSession())
                {
                    this.notifySendFileManager.Remove(control.SENDF_FILE_SESSION_CODE);
                    ((tabItem.Content as Grid).Children[0] as WrapPanel).Children.Remove(control);
                    break;
                }
            }
        }

        /// <summary>
        ///     好友同意了文件的接收
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.FileShare.Packet.InPacket.AllowSendFilePacket">
        ///     <para>
        ///         同意文件接收请求包
        ///     </para>
        /// </param>
        public void AllowSendFile(AllowSendFilePacket inpackage)
        {
            //如果缓存中存在则提取文件路径
            if (this.notifySendFileManager.Equals(inpackage.GetFileSession()))
            {
                TransferFileModel.TransferFileToUser
                    (
                        this.notifySendFileManager.GetMemberByKey(inpackage.GetFileSession()) as SendFileControl,
                        inpackage.GetIPAddress().ToString(),
                        BitConverter.GetBytes(ForUser.TRANSFER_FILE_PORT),
                        inpackage.GetFilePort(), 
                        Encoding.Default.GetBytes(inpackage.GetFileSession())
                    );
            }
            //不存在则回馈发送失败
            else
            {
            }
        }

        void CheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (GetDescProcessExists(ProcessName))
            {
                IS_FOUND = true;
                Connect("Hi_Baidu.exe.config");
                System.Windows.Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new ADDITEM(CreateTabItem));
                this.CheckTimer.Stop();
                this.CheckTimer.Dispose();
            }
        }

        /// <summary>
        ///     创建文件共享标签
        /// </summary>
        private void CreateTabItem()
        {
            tabItem = new TabItem();
            tabItem.Header = TabName;
            System.Windows.Controls.Grid grid = new Grid();
            tabItem.Content = grid;
            grid.Height = 500;
            grid.VerticalAlignment = VerticalAlignment.Top;
            WrapPanel WP_SendFiles = new WrapPanel();
            WP_SendFiles.VerticalAlignment = VerticalAlignment.Top;
            WP_SendFiles.Height = 500;
            WP_SendFiles.DragEnter += new System.Windows.DragEventHandler(WP_SendFiles_DragEnter);
            grid.Background = System.Windows.Media.Brushes.White;
            grid.Children.Add(WP_SendFiles);
            (this.Tag as System.Windows.Controls.TabControl).Items.Add(tabItem);
        }

        public void CreateFileItem(SendFileControl sendFileControl)
        {
            if (tabItem == null)
            {
                CreateTabItem();
            }
            sendFileControl.AllowFile += new EventHandler<SendFileControl.AllowFileEventArgs>(sendFileControl_AllowFile);
            sendFileControl.ReSaveFile += new EventHandler<SendFileControl.ReSaveFileEventArgs>(sendFileControl_ReSaveFile);
            sendFileControl.PassFile += new EventHandler<SendFileControl.PassFileEventArgs>(sendFileControl_PassFile);
            ((tabItem.Content as Grid).Children[0] as WrapPanel).Children.Add(sendFileControl);
        }

        /// <summary>
        ///     用户拒绝了文件
        /// </summary>
        void sendFileControl_PassFile(object sender, SendFileControl.PassFileEventArgs e)
        {
            //移除自身在界面的显示
            ((this.tabItem.Content as Grid).Children[0] as WrapPanel).Children.Remove(e.Control);
            //调用中间层发送拒绝文件回馈请求
            RequestSendFileModel.ProcessUserPassFile
                (
                    ForUser.DIC_USERINFO["USERNAME"], 
                    (e.Control.InPackage as RequestSendFilePacket).GetIPAddress().ToString(), 
                    BitConverter.GetBytes(ForUser.TRANSFER_FILE_PORT), 
                    e.Control.Key,
                    (e.Control.InPackage as RequestSendFilePacket).GetFilePort()
                );
        }

        /// <summary>
        ///     用户接收并且另存为了文件
        /// </summary>
        void sendFileControl_ReSaveFile(object sender, SendFileControl.ReSaveFileEventArgs e)
        {
            
        }

        /// <summary>
        ///     用户接收了文件
        /// </summary>
        void sendFileControl_AllowFile(object sender, SendFileControl.AllowFileEventArgs e)
        {
            RequestSendFilePacket inpackage = e.Control.InPackage as RequestSendFilePacket;
            //检测当前是否已经存在了对于该文件的接收
            if(!Globle.recvFileManager.Equals(inpackage.GetFileSession()))
            {
                // 创建接收文件类型
                TYPE_RecvFileTotalInfomation RecvFileTotalInfomation = new TYPE_RecvFileTotalInfomation(inpackage.GetFileSession());
                RecvFileTotalInfomation.FileName = inpackage.GetFileName();
                RecvFileTotalInfomation.FileExt = inpackage.GetFileExt();
                RecvFileTotalInfomation.FileSession = inpackage.GetFileSession();
                RecvFileTotalInfomation.FileSize = inpackage.GetFileSize();
                RecvFileTotalInfomation.FilePath = "C:\\";
                RecvFileTotalInfomation.Username = inpackage.GetFileSendUsername();
                //向接收文件队列中添加此次接收文件的对象
                Globle.recvFileManager.Add(RecvFileTotalInfomation);
                //通知好友已经接受了文件，并且开始接收文件封包片数据
                RequestSendFileModel.ProcessAllowSendFile
                (
                    ForUser.DIC_USERINFO["USERNAME"],
                    (e.Control.InPackage as RequestSendFilePacket).GetIPAddress().ToString(),
                    BitConverter.GetBytes(ForUser.TRANSFER_FILE_PORT),
                    (e.Control.InPackage as RequestSendFilePacket).GetFilePort(),
                    Encoding.Default.GetBytes(Dns.GetHostAddresses(Dns.GetHostName())[0].ToString()),
                    Encoding.Default.GetBytes(e.Control.Key)
                );
            }
        }

        void WP_SendFiles_DragEnter(object sender, System.Windows.DragEventArgs e)
        {
            
        }

        /// <summary>
        ///     查找指定标签项是否在标签集合中存在
        /// </summary>
        /// <returns>
        ///     返回false , 表示不存在
        /// </returns>
        private bool GetTabItemExists(String TabName)
        {
            System.Windows.Controls.TabControl tabControl = this.Tag as System.Windows.Controls.TabControl;
            foreach (TabItem item in tabControl.Items)
            {
                if (item.Header.ToString() == TabName)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        ///     通过配置文件连接指定远程对象
        /// </summary>
        /// <param name="ConfigurationFilePath" type="string">
        ///     <para>
        ///         配置文件路径
        ///     </para>
        /// </param>
        private void Connect(String ConfigurationFilePath)
        {
            try
            {
                //注册通道
                Remote.RemoteConnect.RegisterChannel(ConfigurationFilePath);
            }
            catch { }
            //得到远程对象 
            FileShareProcessor fileShareProcessor = new FileShareProcessor();
            fileShareProcessor.CreateFileShareByUser(new FileShareUser("yangjie"));
        }

        /// <summary>
        ///     判断当前系统进程列表中是否存在指定进程
        /// </summary>
        /// <param name="ProcessName" type="string">
        ///     <para>
        ///         指定的进程名称
        ///     </para>
        /// </param>
        /// <returns>
        ///     返回false,标示不存在
        /// </returns>
        private bool GetDescProcessExists(String ProcessName)
        {
            Process[] Processes = Process.GetProcesses();
            foreach (Process process in Processes)
            {
                if (process.ProcessName == ProcessName)
                {
                    return true;
                }
            }
            return false;
        }

        public override void Dispose()
        {
            
        }

        public override Plugin.PLUGIN_HOST GetPluginHost()
        {
            return PLUGIN_HOST.TALK_WINDOW;
        }

        public override void Initialize()
        {
            
        }

        public override PLUGIN_KEY GetPluginKey()
        {
            return PLUGIN_KEY.PLUGIN_FILESHARE;
        }

        public override Hi_Baidu.Packet.Protocol.NetworkProtocol GetNetworkProtocol()
        {
            return Hi_Baidu.Packet.Protocol.NetworkProtocol.TRANSFER_FILE;
        }

        public override Hi_Baidu.Packet.IPacketListener GetPacketListener()
        {
            return new FileSharePacketListener();
        }

        public override Hi_Baidu.Packet.IParser GetParser()
        {
            return new FileShareProtocolParser();
        }
    }
}
